
testPrinter('', '', '');

testPrinter('1', '1;', '1');

testPrinter('1+2', '1 + 2;', '1+2');

testPrinter(
'a = 1;b = 2;',

'a = 1;\n' +
'b = 2;',

'a=1;b=2'
);

testPrinter(
'a(1); a(1, 2+3);',

'a(1);\n' +
'a(1, 2 + 3);',
'a(1);a(1,2+3)'
);

testPrinter(
'new Alkaline.Module()',
'new Alkaline.Module();',
'new Alkaline.Module'
);

testPrinter(
'delete Alkaline.Module',
'delete Alkaline.Module;',
'delete Alkaline.Module'
);

testPrinter(
'throw "asdf"',
'throw "asdf";',
'throw "asdf"'
);

testPrinter(
'throw 1,2;',
'throw 1, 2;',
'throw 1,2'
);

testPrinter(
'var asdf',
'var asdf;',
'var asdf'
);

testPrinter(
'var asdf = 2',

'var asdf;\n\
asdf = 2;',

'var asdf;asdf=2'
);

testPrinter(
'"asdf" in window',
'"asdf" in window;',
'"asdf" in window'
);

testPrinter(
'a instanceof b',
'a instanceof b;',
'a instanceof b'
);

testPrinter(
'typeof Object',
'typeof Object;',
'typeof Object'
);

testPrinter(
'(1,"asd").a',
'(1, "asd").a;',
'(1,"asd").a'
);

testPrinter(
'a ? b : c',
'a ? b : c;',
'a?b:c'
);

testPrinter(
'1 ? 2 : 3 + 2',
'1 ? 2 : 3 + 2;',
'1?2:3+2'
);

testPrinter(
'(1 ? 2 : 3) + 2',
'(1 ? 2 : 3) + 2;',
'(1?2:3)+2'
);

testPrinter(
'a = function(){ return 2 }();{1}(3)',

'a = function() {\n\
	return 2;\n\
}();\n\
{\n\
	1;\n\
}\n\
3;',

'a=function(){return 2}();{1}3'
);

testPrinter(
'var a = 1 || (1, 2)',

'var a;\n\
a = 1 || (1, 2);',

'var a;a=1||(1,2)'
);

testPrinter(
'new A(B, C)',
'new A(B, C);',
'new A(B,C)'
);

testPrinter(
'a[b]',
'a[b];',
'a[b]'
);

testPrinter(
'a.b',
'a.b;',
'a.b'
);

testPrinter(
'+ + 1',
'+ +1;',
'+ +1'
);

testPrinter(
'- - 1',
'- -1;',
'- -1'
);

testPrinter(
'+ - 1',
'+-1;',
'+-1'
);

testPrinter(
'a && (b = c)',
'a && (b = c);',
'a&&(b=c)'
);

testPrinter(
'(a = b).c',
'(a = b).c;',
'(a=b).c'
);

testPrinter(
'(a + b)()',
'(a + b)();',
'(a+b)()'
);

testPrinter(
'!(a || b)',
'!(a || b);',
'!(a||b)'
);

testPrinter(
'new (a + b)()',
'new (a + b)();',
'new(a+b)'
);

testPrinter(
'function a() { yield (1, 2); }',
'function a() {\n\
	yield (1, 2);\n\
}',
'function a(){yield(1,2)}'
);

testPrinter(
'delete (a.b, a.c)',
'delete (a.b, a.c);',
'delete(a.b,a.c)'
);

testPrinter(
'typeof (a+b)',
'typeof (a + b);',
'typeof(a+b)'
);

testPrinter(
'typeof (a,b)',
'typeof (a, b);',
'typeof(a,b)'
);

testPrinter(
'void (a+b)',
'void (a + b);',
'void(a+b)'
);

testPrinter(
'void (a,b)',
'void (a, b);',
'void(a,b)'
);

testPrinter(
'void a',
'void a;',
'void a'
);

testPrinter(
'void a + b',
'void a + b;',
'void a+b'
);

testPrinter(
'(!a).b',
'(!a).b;',
'(!a).b'
);

testPrinter(
'(a++).b',
'(a++).b;',
'(a++).b'
);

testPrinter(
'(--a).b',
'(--a).b;',
'(--a).b'
);

testPrinter(
'(!a)()',
'(!a)();',
'(!a)()'
);

testPrinter(
'(a++)()',
'(a++)();',
'(a++)()'
);

testPrinter(
'(--a)()',
'(--a)();',
'(--a)()'
);

testPrinter(
'!(a instanceof b)',
'!(a instanceof b);',
'!(a instanceof b)'
);

testPrinter(
'a++ + ++b',
'a++ + ++b;',
'a++ + ++b'
);

testPrinter(
'(a ? b : c).d',
'(a ? b : c).d;',
'(a?b:c).d'
);

testPrinter(
'a = b ? c : d',
'a = b ? c : d;',
'a=b?c:d'
);

testPrinter(
"'a' + (2-1);",
'"a" + (2 - 1);',
'"a"+(2-1)'
);

testPrinter(
"'a' + (2-1);",
'"a" + (2 - 1);',
'"a"+(2-1)'
);

testPrinter(
"'a' + (2+1);",
'"a" + (2 + 1);',
'"a"+(2+1)'
);

testPrinter(
"'a' + 2+1;",
'"a" + 2 + 1;',
'"a"+2+1'
);

testPrinter(
"('a'+2) + 1;",
'"a" + 2 + 1;',
'"a"+2+1'
);

testPrinter(
"'a' + (2*3);",
'"a" + 2 * 3;',
'"a"+2*3'
);

testPrinter(
"a = (b = 1)",
"a = b = 1;",
"a=b=1"
);

testPrinter(
'1 ? 2 : b = 3',
'1 ? 2 : b = 3;',
'1?2:b=3'
);

testPrinter(
'a = - b;',
'a = -b;',
'a=-b'
);

testPrinter(
'a["b"]',
'a.b;',
'a.b'
);

testPrinter(
'a["."]',
'a["."];',
'a["."]'
);

testPrinter(
'a[""]',
'a[""];',
'a[""]'
);

testPrinter(
'(new a).b',
'new a().b;',
'new a().b'
);

testPrinter(
'new a()(1)',
'new a()(1);',
'new a()(1)'
);

testPrinter(
'a = b = c ? d : e',
'a = b = c ? d : e;',
'a=b=c?d:e'
);

testPrinter(
'a = 1, b = 2',
'a = 1, b = 2;',
'a=1,b=2'
);

testPrinter(
'a(1000);',
'a(1e3);',
'a(1e3)'
);

testPrinter(
'a(1000000);',
'a(1e6);',
'a(1e6)'
);

testPrinter(
'a(123000);',
'a(123e3);',
'a(123e3)'
);

testPrinter(
'a(12300);',
'a(12300);',
'a(12300)'
);

testPrinter(
'a(0xff);',
'a(255);',
'a(255)'
);

testPrinter(
'( {} )',
'({});',
'({})'
);

testPrinter(
'"\\0"',
'"\\0";',
'"\\0"'
);

testPrinter(
'"\\u0061"',
'"a";',
'"a"'
);

testPrinter(
'"\\u0061"',
'"a";',
'"a"'
);

testPrinter(
'"\\\\u0061"',
'"\\\\u0061";',
'"\\\\u0061"'
);

testPrinter(
'"\\\\\\u0061"',
'"\\\\a";',
'"\\\\a"'
);

testPrinter(
'\'"\'',
'"\\"";',
'"\\""'
);

testPrinter(
'"\\""',
'"\\"";',
'"\\""'
);

testPrinter(
'"use strict"; var a = 1;',

'"use strict";\n\
var a;\n\
a = 1;',

'"use strict";var a;a=1'
);

var kw = ['break', 'case', 'catch', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'false', 'finally', 'for', 'function', 'if', 'in',
	'instanceof', 'new', 'null', 'return', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with'].concat(
	// add keywords reserved for future use
	['class', 'const', 'enum', 'export', 'extends', 'import', 'super']);
var kwFutureStrict = ['implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield'];
for (var kwIdx = 0; kwIdx < kw.length; kwIdx++) {
	testPrinter(
	'a["' + kw[kwIdx] + '"]',
	'a["' + kw[kwIdx] + '"];',
	'a["' + kw[kwIdx] + '"]'
	);
	testPrinter(
	'({"' + kw[kwIdx] + '":1})',
	'({\n' +
	'	"' + kw[kwIdx] + '": 1\n' +
	'});',
	'({"' + kw[kwIdx] + '":1})'
	);
	/*
	// TODO: extend current implementation and give warnings for these
	testPrinter(
	'a.' + kw[kwIdx] + '',
	'a["' + kw[kwIdx] + '"];',
	'a["' + kw[kwIdx] + '"]'
	);
	*/
	testPrinter(
	'({' + kw[kwIdx] + ':1})',
	'({\n' +
	'	"' + kw[kwIdx] + '": 1\n' +
	'});',
	'({"' + kw[kwIdx] + '":1})'
	);
}

for (var kwIdx = 0; kwIdx < kwFutureStrict.length; kwIdx++) {
	testPrinter(
	'a["' + kwFutureStrict[kwIdx] + '"]',
	'a.' + kwFutureStrict[kwIdx] + ';',
	'a.' + kwFutureStrict[kwIdx] + ''
	);
	testPrinter(
	'"use strict"; a["' + kwFutureStrict[kwIdx] + '"]',
	
	'"use strict";\n' +
	'a["' + kwFutureStrict[kwIdx] + '"];',
	
	'"use strict";a["' + kwFutureStrict[kwIdx] + '"]'
	);
	testPrinter(
	'function a(){ "use strict"; a["' + kwFutureStrict[kwIdx] + '"]; }; a["' + kwFutureStrict[kwIdx] + '"]',
	
	'function a() {\n' +
	'	"use strict";\n' +
	'	a["' + kwFutureStrict[kwIdx] + '"];\n' +
	'}\n' +
	'a.' + kwFutureStrict[kwIdx] + ';',
	
	'function a(){"use strict";a["' + kwFutureStrict[kwIdx] + '"]}a.' + kwFutureStrict[kwIdx] + ''
	);
}
